

#include <gfx/renderenvironment.h>
#include <gfx/generator/grassinstancegenerator.h>


ceGrassInstanceGenerator::ceGrassInstanceGenerator (unsigned c)
	: iInstanceGenerator ()
	, _c (c)
{
	CE_OBJECT_CONSTR;
}

void ceGrassInstanceGenerator::SetVertices (ceVector3f* vertices, unsigned num)
{
	_vertices = vertices;
	_num = num;

	_bbox.Clear ();
	for (unsigned i=0; i<_num; i++)
		{
			_bbox.Add (vertices[i]);
		}
	_bbox.Update ();
}

void ceGrassInstanceGenerator::Generate (const ceRenderEnvironment&			env, 
                                         iDevice*                       device,
																				 std::vector<ceInstancedData>&	data,
																				 unsigned&											num, 
																				 unsigned&											maxNum)
{
	unsigned v = _c;
	_c++;
	if (v % 2)
		{
			return;
		}
	ceInstancedData& d = data[0];
	if (d.Vec4 == 0)
		{
			d.Vec4 = new ceVector4f [_num];
			maxNum = _num;
		}

	ceVector3f dt = env.ProjectionMatrix.Project (ceVector3f (0.0f, 0.0f, -50.0f));
	float maxZ = dt.z;
	ceMatrix4f M = env.ProjectionMatrix * env.ViewMatrix * env.ModelMatrix;
	float dist = 1.2;
	unsigned n = 0;
	const ceVector3f& min = _bbox.GetMin ();
	const ceVector3f& max = _bbox.GetMax ();
	ceVector3f diff = max - min;
	for (unsigned i=0; i<_num; i++)
		{
			ceVector3f p = M.Project (_vertices[i]);
			if (p.x < -dist || p.x > dist ||
					p.y < -dist || p.y > dist ||
					p.z < -dist || p.z > maxZ)
				{
					continue;
				}
			ceVector3f delta = (_vertices[i] - min) / diff;
			float disp = delta.x + delta.y + delta.z;
			d.Vec4[n++] = ceVector4f (_vertices[i], disp);
		}
	num = n;
}
